#include "stdafx.h"
#include "ui_single_object_viewer.h"

_SSL_BEGIN
_SSUIL_BEGIN

UISingleObjectViewer::UISingleObjectViewer()
{
	properties_ |= kControlPropertyAcceptArrowKey;

	//
	view_x_offset_ = 0;
	view_y_offset_ = 0;

	view_x_offset_min_ = 0;
	view_x_offset_max_ = 0;
	view_y_offset_min_ = 0;
	view_y_offset_max_ = 0;
}

UISingleObjectViewer::~UISingleObjectViewer()
{

}

bool UISingleObjectViewer::ApplyAttributes(IUIBuilderInterface *ui_builder, 
	IUIXMLDocumentInterface *xml_document, UIXmlNode node)
{
	if(!__super::ApplyAttributes(ui_builder, xml_document, node))
		return false;

	UIXmlAttribute attribute = NULL;
	attribute = xml_document->FirstAttribute(node, "horizontal_slider");
	if(attribute != NULL)
	{
		horizontal_slider_name_ = auto_cvt(xml_document->AttributeValue(attribute)).c_tstr();
	}

	attribute = xml_document->FirstAttribute(node, "vertical_slider");
	if(attribute != NULL)
	{
		vertical_slider_name_ = auto_cvt(xml_document->AttributeValue(attribute)).c_tstr();
	}

	return true;
}

void UISingleObjectViewer::DoEvent(UIEvent &evt)
{
	if(evt.type == kEvtMouseWheel)
	{
		if(child_items_.size() == 0)
			return;

		int change_v = (int)evt.wparam;
		if(evt.key_state == kMWDirDown)
			change_v = -change_v;
		if(vertical_slider_ != NULL && vertical_slider_->IsVisibled())
			SetYOffset((int)(view_y_offset_+change_v));
		else if(horizontal_slider_ != NULL && horizontal_slider_->IsVisibled())
			SetXOffset((int)(view_x_offset_+change_v));
		return;
	}else if(evt.type == kEvtKeyDown)
	{
		if(vertical_slider_ != NULL)
			vertical_slider_->ScrollByKey(evt.key_character);
		else if(horizontal_slider_ != NULL)
			horizontal_slider_->ScrollByKey(evt.key_character);
		return;
	}
	__super::DoEvent(evt);
}

UINT UISingleObjectViewer::GetProperties()
{
	UINT propeties = __super::GetProperties();
	if( (vertical_slider_ != NULL && vertical_slider_->IsVisibled()) || 
		(horizontal_slider_ != NULL && horizontal_slider_->IsVisibled()) )
		propeties |= kControlPropertyAcceptMouseWheel|kControlPropertyHittest;
	else
		propeties &= ~(kControlPropertyAcceptMouseWheel|kControlPropertyHittest);
	return propeties;
}

bool UISingleObjectViewer::AddChild(IUIControlInterface *control)
{
	if(control == NULL)
		return false;
	child_items_.clear();
	UIPresetPosition preset_pos = control->GetPresetPosition();
	if(!horizontal_slider_name_.empty() || horizontal_slider_ != NULL)
	{
		if(!preset_pos.HasWidth())
			return false;
	}
	if(!vertical_slider_name_.empty() || vertical_slider_ != NULL)
	{
		if(!preset_pos.HasHeight())
			return false;
	}
	view_x_offset_ = 0;
	view_y_offset_ = 0;
	preset_pos.SetLeft(view_x_offset_, true).SetTop(view_y_offset_, true);
	control->SetPresetPosition(preset_pos);
	return __super::AddChild(control);
}
void UISingleObjectViewer::OnRecalcChildsLayoutOnSizeChange()
{
	__super::OnRecalcChildsLayoutOnSizeChange();

	scoped_ref_ptr<IUIManagerInterface> win_man = GetWindowManager();

	if(!horizontal_slider_name_.empty() && win_man != NULL && win_man->GetContent() != NULL)
	{
		scoped_ref_ptr<IUIControlInterface> c = this->FindControl(horizontal_slider_name_.c_str());
		if(c != NULL)
		{
			UISlider *sbc = dynamic_cast<UISlider *>(c.get());
			if(sbc != NULL)
			{
				SetHorizontalSlider(sbc);
			}
		}
		horizontal_slider_name_.clear();
	}

	if(!vertical_slider_name_.empty())
	{
		scoped_ref_ptr<IUIControlInterface> c = this->FindNearstControl(vertical_slider_name_.c_str());
		if(c != NULL)
		{
			UISlider *sbc = dynamic_cast<UISlider *>(c.get());
			if(sbc != NULL)
			{
				SetVerticalSlider(sbc);
			}
		}
		vertical_slider_name_.clear();
	}

	if(child_items_.size() == 0)
		return;
	SetXOffset(view_x_offset_);
	SetYOffset(view_y_offset_);
}


int UISingleObjectViewer::GetControlAutoWidth()
{
	if(child_items_.size() == 0)
		return __super::GetControlAutoWidth();
	return dynamic_cast<IUIAutoSizeInterface*>(child_items_[0].get())->GetObjectAutoWidth();
}

int UISingleObjectViewer::GetControlAutoHeight()
{
	if(child_items_.size() == 0)
		return __super::GetControlAutoHeight();
	return dynamic_cast<IUIAutoSizeInterface*>(child_items_[0].get())->GetObjectAutoHeight();
}

bool UISingleObjectViewer::ScrollToTop()
{
	if(vertical_slider_ == NULL)
		return false;
	return SetYOffset(0);
}

bool UISingleObjectViewer::ScrollToLeft()
{
	if(horizontal_slider_ == NULL)
		return false;
	return SetXOffset(0);
}

bool UISingleObjectViewer::ScrollToControl(IUIControlInterface *control)
{
	if(control == NULL)
		return false;

	if(child_items_.size() == 0)
		return false;

	IUIControlInterfaceAutoPtrs childs = child_items_[0]->GetChilds();
	IUIControlInterfaceAutoPtrs::iterator iter=child_items_.begin();
	for(; iter!=child_items_.end(); iter++)
	{
		if((*iter) == NULL)
			continue;
		if((*iter)->compare(control) || (*iter)->IsControlExists(control))
			break;
	}
	if(iter == childs.end())
		return false;

	control = *iter;

	UIRect pst = control->GetPosition();

	if(vertical_slider_ != NULL && vertical_slider_->IsVisibled())
	{
		int v = vertical_slider_->GetValue();
		pst.top += v;
		pst.bottom += v;

		if(v + GetClientSize().cy < pst.bottom)
			v = pst.bottom - GetClientSize().cy;
		else if(v > pst.top)
			v = pst.top;
		SetYOffset(-v);
	}

	if(horizontal_slider_ != NULL && horizontal_slider_->IsVisibled())
	{
		int v = horizontal_slider_->GetValue();

		if(v + GetClientSize().cx < pst.right)
			v = pst.right - GetClientSize().cx;
		else if(v > pst.left)
			v = pst.left;
		SetXOffset(v);
	}

	return true;
}

void UISingleObjectViewer::SetHorizontalSlider(UISlider *hs)
{
	if(UIValueParseUtil::CompareControl(horizontal_slider_, hs))
		return;

	if(horizontal_slider_ != NULL)
		horizontal_slider_->OnNotify -= make_delegate(this, &UISingleObjectViewer::DelegateOnSliderNotify);
	horizontal_slider_ = hs;
	if(vertical_slider_ == NULL)
		return;
	horizontal_slider_->OnNotify += make_delegate(this, &UISingleObjectViewer::DelegateOnSliderNotify);
	if(view_x_offset_min_ == view_x_offset_max_)
	{
		horizontal_slider_->SetVisible(false);
	}else
	{
		horizontal_slider_->SetVisible(true);
		horizontal_slider_->SetRange(-view_x_offset_max_, -view_x_offset_min_);
		horizontal_slider_->SetValue(-view_x_offset_);
	}
}

void UISingleObjectViewer::SetVerticalSlider(UISlider *vs)
{
	if(UIValueParseUtil::CompareControl(vertical_slider_, vs))
		return;

	if(vertical_slider_ != NULL)
		vertical_slider_->OnNotify -= make_delegate(this, &UISingleObjectViewer::DelegateOnSliderNotify);
	vertical_slider_ = vs;
	if(vertical_slider_ == NULL)
		return;
	vertical_slider_->OnNotify += make_delegate(this, &UISingleObjectViewer::DelegateOnSliderNotify);
	if(view_y_offset_min_ == view_y_offset_max_)
	{
		vertical_slider_->SetVisible(false);
	}else
	{
		vertical_slider_->SetVisible(true);
		vertical_slider_->SetRange(-view_y_offset_max_, -view_y_offset_min_);
		vertical_slider_->SetValue(-view_y_offset_);
	}
}

bool UISingleObjectViewer::SetXOffset(int new_offset)
{
	if(child_items_.size() == 0)
		return false;

	int content_cx = child_items_[0]->GetPosition().Width();

	int view_x_offset_min = -(content_cx - GetClientSize().cx);
	int view_x_offset_max = 0;
	if(view_x_offset_min > view_x_offset_max)
		view_x_offset_min = view_x_offset_max;

	if(new_offset < view_x_offset_min)
		new_offset = view_x_offset_min;
	if(new_offset > view_x_offset_max)
		new_offset = view_x_offset_max;

	if(view_x_offset_min != view_x_offset_min_ || view_x_offset_max != view_x_offset_max_)
	{
		view_x_offset_min_ = view_x_offset_min;
		view_x_offset_max_ = view_x_offset_max;

		if(horizontal_slider_ != NULL)
		{
			if(view_x_offset_min_ == view_x_offset_max_)
			{
				horizontal_slider_->SetVisible(false);
			}else
			{
				horizontal_slider_->SetVisible(true);
				horizontal_slider_->SetRange(-view_x_offset_max_, -view_x_offset_min_);
			}
		}

		SendNotify(
			UINotify(_T("x_scroll_set_range"), this, MAKEINT64(view_x_offset_max_, view_x_offset_min_))
			);
	}

	if(new_offset != view_x_offset_)
	{
		view_x_offset_ = new_offset;

		if(horizontal_slider_ != NULL)
		{
			horizontal_slider_->SetValue(-view_x_offset_);
		}

		SendNotify(
			UINotify(_T("x_scroll_set_value"), this, MAKEINT64(0, view_x_offset_))
			);

		UIPresetPosition preset_pos = child_items_[0]->GetPresetPosition();
		preset_pos.SetLeft(view_x_offset_, true);
		child_items_[0]->SetPresetPosition(preset_pos);
		SetNeedUpdate(true);
	}

	return true;
}

bool UISingleObjectViewer::SetYOffset(int new_offset)
{
	if(child_items_.size() == 0)
		return false;

	int content_cy = child_items_[0]->GetPosition().Height();

	int view_y_offset_min = -(content_cy - GetClientSize().cy);
	int view_y_offset_max = 0;
	if(view_y_offset_min > view_y_offset_max)
		view_y_offset_min = view_y_offset_max;

	if(new_offset < view_y_offset_min)
		new_offset = view_y_offset_min;
	if(new_offset > view_y_offset_max)
		new_offset = view_y_offset_max;

	if(view_y_offset_min != view_y_offset_min_ || view_y_offset_max != view_y_offset_max_)
	{
		view_y_offset_min_ = view_y_offset_min;
		view_y_offset_max_ = view_y_offset_max;

		if(vertical_slider_ != NULL)
		{
			if(view_y_offset_min_ == view_y_offset_max_)
			{
				vertical_slider_->SetVisible(false);
			}else
			{
				vertical_slider_->SetVisible(true);
				vertical_slider_->SetRange(-view_y_offset_max_, -view_y_offset_min_);
			}
		}

		SendNotify(
			UINotify(_T("y_scroll_set_range"), this, MAKEINT64(view_y_offset_max_, view_y_offset_min_))
			);
	}

	if(new_offset != view_y_offset_)
	{
		view_y_offset_ = new_offset;

		if(vertical_slider_ != NULL)
		{
			vertical_slider_->SetValue(-view_y_offset_);
		}

		SendNotify(
			UINotify(_T("y_scroll_set_value"), this, MAKEINT64(0, view_y_offset_))
			);

		UIPresetPosition preset_pos = child_items_[0]->GetPresetPosition();
		preset_pos.SetTop(view_y_offset_, true);
		child_items_[0]->SetPresetPosition(preset_pos);
		SetNeedUpdate(true);
	}

	return true;
}

bool UISingleObjectViewer::DelegateOnSliderNotify(void* tag)
{
	UINotify *nty = (UINotify*)tag;
	if(nty == NULL)
		return false;

	if(nty->type == _T("mousewheel"))
	{
		UIEvent evt;
		evt.type = kEvtMouseWheel;
		evt.key_state = (unsigned short)nty->lparam;
		evt.wparam = nty->wparam;
		evt.relative_control = nty->sender;
		DoEvent(evt);
		return false;
	}

	if(horizontal_slider_ != NULL && nty->sender == horizontal_slider_)
	{
		int v = -horizontal_slider_->GetValue();
		if(v != view_x_offset_)
		{
			SetXOffset(v);
		}
	}

	if(vertical_slider_ != NULL && nty->sender == vertical_slider_)
	{
		int v = -vertical_slider_->GetValue();
		if(v != view_y_offset_)
		{
			SetYOffset(v);
		}
	}

	return false;
}

_SSUIL_END
_SSL_END
